package com.googlecode.simplexer.implementation;

import com.googlecode.simplexer.*;
import com.googlecode.simplexer.io.CharInputSequence;
import com.googlecode.simplexer.io.CharOutputSequence;
import com.googlecode.simplexer.io.implementation.*;
import com.googlecode.simplexer.validator.*;

/**
 * Selectively write tokens to the output files.
 * 
 * @author Sam Huang
 */
public class SimpleMappedLexer extends SimpleLexer implements MappedLexer {
	public static final String[] extensions = new String[] { ".xcc", ".jj",
			".jjt" };

	public static boolean isIntendedFile(String fileName) {
		for (String extension : extensions) {
			if (fileName.endsWith(extension)) {
				return true;
			}
		}

		return false;
	}

	protected boolean dump = true;

	protected String inputFileName = "";

	protected String outputFileName = "";

	protected CharOutputSequence outputSequence = null;

	public SimpleMappedLexer(CharInputSequence s) {
		super(s);
		setCharOutputSequence(ConsoleCharOutputSequence.getInstance());
	}

	public SimpleMappedLexer(CharInputSequence cs, CharOutputSequence outputSource)
			throws Exception {
		super(cs);
		setCharOutputSequence(outputSource);
	}

	public void dump(boolean dump) {
		if (dump && this.dump && outputSequence != null) {
			outputSequence.append(tk);
			// printer.print(" ");
		}
	}

	@Override
	public String forward(int length) {
		tk = super.forward(length);
		dump(true);
		return tk;
	}

	@Override
	public String forward(String token) {
		tk = super.forward(token);
		dump(true);
		return tk;
	}

	@Override
	public String forwardUntil(char chr) {
		tk = super.forwardUntil(chr);
		dump(true);
		return tk;
	}

	@Override
	public String forwardUntil(String token) {
		tk = super.forwardUntil(token);
		dump(true);
		return tk;
	}

	@Override
	public String forwardUntil(Validator v) {
		tk = super.forwardUntil(v);
		dump(true);
		return tk;
	}

	public String getOutputFileName() {
		return this.outputFileName;
	}

	public String nextchar(boolean dump, char chr)
			throws UnsupportedOperationException {
		tk = String.valueOf(super.nextchar(chr));
		dump(dump);
		return tk;
	}

	public String nexttok(boolean dump) {
		tk = super.nexttok();
		dump(dump);
		return tk;
	}
	
	@Override
	public String nexttok(String...expected) {
		tk = super.nexttok(expected);
		dump(true);
		return tk;
	}

	@Override
	public String nexttok(Validator...validators) {
		tk = super.nexttok(validators);
		dump(true);
		return tk;
	}
	
	@Override
	public String nexttok(int length) {
		tk = super.nexttok(length);
		dump(dump);
		return tk;
	}

	public String nexttok(boolean dump, int length) {
		tk = super.nexttok(length);
		dump(dump);
		return tk;
	}

	public String nexttok(boolean dump, String... strings) {
		tk = super.nexttok(strings);
		dump(dump);
		return tk;
	}

	public String nexttok(boolean dump, Validator... verifiers) {
		tk = super.nexttok(verifiers);
		dump(dump);
		return tk;
	}

	public SimpleMappedLexer print(char chr) {
		if (this.dump && outputSequence != null) {
			outputSequence.append(chr);
		}
		return this;
	}

	public SimpleMappedLexer print(String message) {
		if (this.dump && outputSequence != null) {
			outputSequence.append(message);
			// printer.print(" ");
		}
		return this;
	}

	public void setDump(boolean dump) {
		this.dump = dump;
	}

	public String skip(boolean dump, char chr) {
		tk = super.skipTo(chr);
		dump(dump);
		return tk;
	}

	/* (non-Javadoc)
	 * @see net.java.dev.simplexer.MappedLexer#getCharOutputSequence()
	 */
	public CharOutputSequence getCharOutputSequence() {
		return this.outputSequence;
	}

	/* (non-Javadoc)
	 * @see net.java.dev.simplexer.MappedLexer#setCharOutputSequence(net.java.dev.simplexer.io.CharOutputSequence)
	 */
	public void setCharOutputSequence(CharOutputSequence ss) throws UnsupportedOperationException {
		this.outputSequence = ss;
	}

	public CharInputSequence getCharInputSequence() {
		return inputSource;
	}

	public void close() {
		super.close();
		outputSequence.close();
	}
}
